using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using MEA.AE_Data;
using MEA.AE_Data.Access;
using MEA.AE_Data.Config;
using MEA.Misc;

namespace MEA.AE_BusinessLogic
{
	public class FlashLayer : I_BusinessLogic
	{
		private enum EVerifyFlashConditions
		{
			eNoActiveECUSite,
			eBothECUActive,
			eonlyAECUActive,
			eonlyBECUActive,
			eIgnoreFlCond
		}

		private IBaseService baseServiceA;

		private IBaseService baseServiceB;

		private IEngine12 engA;

		private IEngine12 engB;

		private ConfigFlash.e_Flash_States flashState;

		private IFlashService flashServiceA;

		private IFlashService flashServiceB;

		private IBaseService currentFlashECU;

		private string flashContainerPath = string.Empty;

		private ushort flashIterationCounter;

		private bool eeprom_backup_complete;

		private bool flashError_flight_prohibited;

		private string errorMessage = string.Empty;

		private string dtcText_SM_Main = string.Empty;

		private string flashLog_FilePathAndName = string.Empty;

		private MemoryStream flashLog_originalStream;

		private StreamWriter flashLog_Writer;

		private bool flashLog_EngineID_Completed;

		private bool flashLog_Active;

		private bool[] processActive;

		private bool[] processError;

		private bool notChangedECUA;

		private bool notChangedECUB;

		private FlashContainer flash_containerA;

		private FlashContainer flash_containerB;

		private FlashContainer flash_container;

		private IFlashConditionEvaluator flash_ConditionEvaluator;

		private byte[] bufUnModified = new byte[ConfigData.FlashMemorySize_si];

		private byte[] bufZipped = new byte[ConfigData.FlashMemorySize_si / 10];

		private byte[] bufEncrypted = new byte[ConfigData.FlashMemorySize_si / 10];

		private Thread thread_standard;

		private string XMLWizardScript;

		private string exitReason = string.Empty;

		private bool bFTCOk;

		private ScriptingLayer fscriptLayer;

		private bool ignoringFLCond;

		private FlashSelectV04 flashSelectV04;

		private FlashBlock.EFD_Types selectedFCTVer = FlashBlock.EFD_Types.eFD_NoEFD_Type;

		private string XMLWizardPostScript;

		public IFlashService FlashServiceA
		{
			get
			{
				return flashServiceA;
			}
			set
			{
				flashServiceA = value;
			}
		}

		public IFlashService FlashServiceB
		{
			get
			{
				return flashServiceB;
			}
			set
			{
				flashServiceB = value;
			}
		}

		public bool Eeprom_backup_complete
		{
			get
			{
				return eeprom_backup_complete;
			}
			set
			{
				throw new NotImplementedException("missing: threadsafe assign of variable");
			}
		}

		public bool FlashError_flight_prohibited
		{
			get
			{
				return flashError_flight_prohibited;
			}
			set
			{
				flashError_flight_prohibited = value;
			}
		}

		public bool FlashLog_EngineID_Completed
		{
			get
			{
				return flashLog_EngineID_Completed;
			}
			set
			{
				flashLog_EngineID_Completed = value;
			}
		}

		public bool FlashLog_Active
		{
			get
			{
				return flashLog_Active;
			}
		}

		public event BaseService.AddConsoleHandler ev_AddConsoleEvent;

		public event EventHandler ev_SessionLogTriggerSave;

		public event BaseService.LogFehlerHandler ev_LogFehler;

		public event EventHandler<ServiceLayerBoolEventArg> ev_ProgressClose;

		public event EventHandler<ServiceLayerProgressSetupEventArg> ev_ProgressSetup;

		public event EventHandler<ServiceLayerStringEventArg> ev_ProgressStep;

		public event EventHandler<ServiceLayerStringEventArg> ev_ProgressDetailStep;

		public event EventHandler<ServiceLayerBoolEventArg> ev_ProgressDetailClose;

		public event EventHandler<ServiceLayerIntEventArg> ev_ProgressDetailSetup;

		public event EventHandler<ServiceLayerStringEventArg> ev_ScriptRun;

		public event EventHandler<ServiceLayerStreamEventArg> ev_EEPROM_BackupTrigger;

		public event EventHandler<ServiceLayerStreamEventArg> ev_LogAddEngineID;

		public event EventHandler ev_EEPROM_RestoreTrigger;

		public event EventHandler<ServiceLayerBoolEventArg> ev_flasLayer_FlashCondIgnoreChanged;

		public event EventHandler ev_DTC_Clear;

		public event EventHandler<ServiceLayerStringEventArg> ev_EngLog_Save;

		public event EventHandler ev_DTC_Read;

		public event EventHandler<ServiceLayerStringEventArg> ev_Flash_Successful;

		public event EventHandler<ServiceLayerStringEventArg> ev_Flash_Error;

		public FlashLayer(IBaseService baseA, IBaseService baseB, IFlashService flashA, IFlashService flashB, IEngine12 eng12A, IEngine12 eng12B)
		{
			flashServiceA = flashA;
			flashServiceB = flashB;
			flashServiceA.ev_AddConsoleEvent += h_flashService_ev_AddConsoleEvent;
			flashServiceB.ev_AddConsoleEvent += h_flashService_ev_AddConsoleEvent;
			baseServiceA = baseA;
			baseServiceB = baseB;
			flashLog_Active = false;
			eeprom_backup_complete = false;
			flashError_flight_prohibited = false;
			engA = eng12A;
			engB = eng12B;
			flash_ConditionEvaluator = new FlashConditionEvaluator(baseServiceA.EcuData, baseServiceB.EcuData, engA, engB);
			processError = new bool[4];
			processActive = new bool[4];
			for (int i = 0; i < processError.Length; i++)
			{
				processError[i] = false;
				processActive[i] = false;
			}
			currentFlashECU = baseServiceA;
			ev_AddConsoleEvent += Log_Add;
			ev_ProgressStep += Log_Add_ev_ProgressStep;
		}

		private void Log_Add_ev_ProgressStep(object sender, ServiceLayerStringEventArg e)
		{
			if (e.Message.StartsWith("ECU"))
			{
				Log_Add(e.Message.Substring(7), Color.Black, e.Message.Substring(0, 7));
			}
			else
			{
				Log_Add(e.Message, Color.Black, "");
			}
		}

		private void Log_Init()
		{
			try
			{
				string wizardEncryptedOutput_FileExtension = ConfigData.WizardEncryptedOutput_FileExtension;
				int num = 0;
				flashLog_EngineID_Completed = false;
				flashLog_FilePathAndName = ConfigData.LogRootPath + "\\Flash";
				if (baseServiceA.EcuData.EcuSerialNumber.Contains("."))
				{
					flashLog_FilePathAndName = flashLog_FilePathAndName + "\\FlashLog_ECU_NR_Error_" + DateTime.UtcNow.ToString("yyyyMMdd_hhmmss") + wizardEncryptedOutput_FileExtension;
				}
				else
				{
					string text = flashLog_FilePathAndName;
					flashLog_FilePathAndName = text + "\\FlashLog_" + baseServiceA.EcuData.EcuSerialNumber + "_" + DateTime.UtcNow.ToString("yyyyMMdd_hhmmss") + wizardEncryptedOutput_FileExtension;
				}
				flashLog_originalStream = new MemoryStream();
				flashLog_Writer = new StreamWriter(flashLog_originalStream, Encoding.UTF8);
				if (this.ev_LogAddEngineID != null)
				{
					this.ev_LogAddEngineID(this, new ServiceLayerStreamEventArg(flashLog_originalStream, flashLog_FilePathAndName));
				}
				Thread.Sleep(20);
				while (!flashLog_EngineID_Completed)
				{
					Application.DoEvents();
					Thread.Sleep(20);
					if (num++ >= 5)
					{
						flashLog_EngineID_Completed = false;
						throw new FlashAbortExeption("Error when creating flash-logfile. Process aborted!");
					}
				}
				Console.WriteLine("Log_Init; counter = {0};", num);
				flashLog_Writer.WriteLine();
				flashLog_Active = true;
			}
			catch (FlashAbortExeption flashAbortExeption)
			{
				throw new FlashAbortExeption(flashAbortExeption.Message);
			}
			catch (Exception)
			{
			}
		}

		private void Log_Add(string msg, Color c, string AB)
		{
			if (flashLog_Writer != null && flashLog_Active)
			{
				string text = "";
				if (AB.Length > 0)
				{
					text = " ";
				}
				flashLog_Writer.WriteLine(AB + text + msg);
				flashLog_Writer.Flush();
			}
		}

		private void Log_Save()
		{
			MemoryStream memoryStream = new MemoryStream();
			new CryptedCompression();
			if (flashLog_Writer != null)
			{
				flashLog_Writer.Flush();
			}
			flashLog_Active = false;
			if (flashLog_originalStream == null || !flashLog_originalStream.CanRead)
			{
				return;
			}
			try
			{
				ServiceLayer.SecurityEncryptToFile(flashLog_FilePathAndName, flashLog_originalStream);
			}
			catch
			{
			}
			finally
			{
				memoryStream.Close();
				flashLog_originalStream.Close();
			}
		}

		public void ErrorReportNegResponse(byte fehlerid)
		{
			if (this.ev_AddConsoleEvent != null)
			{
				this.ev_AddConsoleEvent("Negative response: ", Color.Black, "            ");
				switch (fehlerid)
				{
				case 18:
					this.ev_AddConsoleEvent("Invalid format", Color.Black, "            ");
					break;
				case 16:
					this.ev_AddConsoleEvent("General reject", Color.Black, "            ");
					break;
				case 34:
					this.ev_AddConsoleEvent("Condition is not correct or request sequence error", Color.Black, "            ");
					break;
				case 49:
					this.ev_AddConsoleEvent("Request out of range", Color.Black, "            ");
					break;
				case 51:
					this.ev_AddConsoleEvent("Security access denied", Color.Black, "            ");
					break;
				case 53:
					this.ev_AddConsoleEvent("Invalid key", Color.Black, "            ");
					break;
				case 254:
					this.ev_AddConsoleEvent("Programming error", Color.Black, "            ");
					break;
				default:
					this.ev_AddConsoleEvent(string.Format("{0:x2}", fehlerid), Color.Black, "            ");
					break;
				}
			}
		}

		public void AbortThread()
		{
			Log_Save();
			if (this.ev_SessionLogTriggerSave != null)
			{
				this.ev_SessionLogTriggerSave(this, null);
			}
			if (thread_standard != null)
			{
				thread_standard.Abort();
			}
		}

		private void h_flashService_ev_AddConsoleEvent(string s, Color c, string AB)
		{
			if (this.ev_AddConsoleEvent != null)
			{
				this.ev_AddConsoleEvent(s, c, AB);
			}
		}

		public void StartFlashProcess(string logpath, ScriptingLayer scriptLayer)
		{
			fscriptLayer = scriptLayer;
			flashContainerPath = logpath;
			flash_containerA = null;
			flash_containerB = null;
			exitReason = string.Empty;
			if (!ECU_VerifyBothConnected())
			{
				return;
			}
			bFTCOk = FC_ContainerLoad();
			ushort ecuHwVersionCode = baseServiceA.EcuData.EcuHwVersionCode;
			string engineType = baseServiceA.EcuData.EngineType;
			if (ecuHwVersionCode == 0)
			{
				ecuHwVersionCode = baseServiceB.EcuData.EcuHwVersionCode;
				engineType = baseServiceB.EcuData.EngineType;
			}
			if (flash_containerA.File_fct_version >= 0.5f)
			{
				ignoringFLCond = false;
				if (ConfigFlash.IgnoreFlashCond || flash_containerA.Conditions_ignore)
				{
					ignoringFLCond = true;
				}
				flashSelectV04 = new FlashSelectV04();
				flashSelectV04.ev_FlashFC += FlashRoutineComplete;
				flashSelectV04.setFlashSelectV04(ref flash_containerA, ecuHwVersionCode, engineType, ignoringFLCond);
				flashSelectV04.Show();
			}
			else
			{
				if (bFTCOk && MessageBox.Show(string.Format(arg2: (ecuHwVersionCode != 0) ? ((string)ConfigData.HwRevTable[ecuHwVersionCode]) : "unknown (000)", format: "Do you want to flash software version {0}_{1} to hardware version ( {2} )", arg0: flash_containerA.Conditions_sw_v, arg1: flash_containerA.Conditions_ds_v), ConfigData.WizardSwName, MessageBoxButtons.YesNo) != DialogResult.Yes)
				{
					errorMessage += "User canceled, process aborted!";
					bFTCOk = false;
					selectedFCTVer = FlashBlock.EFD_Types.eFD_NoEFD_Type;
				}
				FlashRoutineComplete(null, null);
			}
		}

		private void FlashRoutineComplete(object sender, EventArgs e)
		{
			try
			{
				if (flash_containerA == null)
				{
					return;
				}
				if (sender != null)
				{
					flashSelectV04.ev_FlashFC -= FlashRoutineComplete;
					FlashSelectV04.SFlashResult sFlashResult = (FlashSelectV04.SFlashResult)sender;
					selectedFCTVer = sFlashResult.fdType;
					switch (sFlashResult.errCode)
					{
					case FlashSelectV04.EFlashingErrorCode.eAbbort:
						errorMessage += "User canceled, process aborted!";
						break;
					case FlashSelectV04.EFlashingErrorCode.eNotEvoluated:
						errorMessage = "Flash condition evaluation of both ECUs failed, SW-update process prohibited, engine unserviceable;\r\n Restart Wizard and tray again; Please contact Austro Engine After Sales.";
						break;
					}
					if (selectedFCTVer == FlashBlock.EFD_Types.eFD_NoEFD_Type)
					{
						bFTCOk = false;
						if (ignoringFLCond)
						{
							errorMessage = "Flash condition evaluation of both ECUs failed, SW-update process prohibited, engine unserviceable;\r\n Restart Wizard and tray again; Please contact Austro Engine After Sales.";
						}
						else
						{
							errorMessage += "User canceled, process aborted!";
						}
					}
				}
				thread_standard = new Thread(TH_FlashRoutineComplete);
				thread_standard.Name = "TH_FlashRoutineComplete";
				thread_standard.Start();
			}
			catch (FlashAbortExeption)
			{
				Log_Save();
				baseServiceA.CommunicationStop();
				baseServiceB.CommunicationStop();
			}
		}

		private void SM_Main()
		{
			EVerifyFlashConditions eVerifyFlashConditions = EVerifyFlashConditions.eNoActiveECUSite;
			bool flag = false;
			if (bFTCOk)
			{
				if (flash_containerA.File_fct_version >= 0.5f)
				{
					bFTCOk = flash_containerA.DelNeedlesFCTData(selectedFCTVer);
					bFTCOk &= flash_containerB.DelNeedlesFCTData(selectedFCTVer);
				}
				flash_container = flash_containerA;
				switch (ECUActiveTest())
				{
				case EVerifyFlashConditions.eIgnoreFlCond:
					flag = true;
					goto IL_0102;
				case EVerifyFlashConditions.eonlyAECUActive:
					flag = flash_ConditionEvaluator.Evaluate_FlashConditions(ConfigData.e_ECUID.A, ref flash_containerA, ref exitReason);
					goto IL_0102;
				case EVerifyFlashConditions.eonlyBECUActive:
					flag = flash_ConditionEvaluator.Evaluate_FlashConditions(ConfigData.e_ECUID.B, ref flash_containerB, ref exitReason);
					goto IL_0102;
				case EVerifyFlashConditions.eBothECUActive:
					flag = flash_ConditionEvaluator.Evaluate_FlashConditions(ConfigData.e_ECUID.A, ref flash_containerA, ref exitReason);
					if (flag)
					{
						flag &= flash_ConditionEvaluator.Evaluate_FlashConditions(ConfigData.e_ECUID.B, ref flash_containerB, ref exitReason);
					}
					goto IL_0102;
				default:
					flag = false;
					goto IL_0102;
				case EVerifyFlashConditions.eNoActiveECUSite:
					{
						flashState = ConfigFlash.e_Flash_States.ERROR;
						throw new FlashAbortExeption("Flash condition evaluation of both ECUs failed, SW-update process prohibited, engine unserviceable;\r\n Restart Wizard and tray again; Please contact Austro Engine After Sales.");
					}
					IL_0102:
					if (flag)
					{
						exitReason = string.Empty;
						exitReason = SM_Sub_FCM_Check(1);
						if (exitReason != string.Empty)
						{
							dtcText_SM_Main = exitReason;
						}
						for (ConfigData.e_ECUID e_ECUID = ConfigData.e_ECUID.A; e_ECUID <= ConfigData.e_ECUID.B; e_ECUID++)
						{
							flashState = ConfigFlash.e_Flash_States.WRITE_FINGERPRINT;
							switch (e_ECUID)
							{
							case ConfigData.e_ECUID.A:
								flash_container = flash_containerA;
								break;
							case ConfigData.e_ECUID.B:
								flash_container = flash_containerB;
								flash_containerA = null;
								break;
							}
							do
							{
								switch (flashState)
								{
								case ConfigFlash.e_Flash_States.WRITE_FINGERPRINT:
									SM_Sub_FingerprintWrite(e_ECUID);
									break;
								case ConfigFlash.e_Flash_States.FILTER_BLOCKS_ALREADY_IN_ECU:
									SM_Sub_SkipRedundantAreas(e_ECUID);
									break;
								case ConfigFlash.e_Flash_States.ERASE_FIRST_BLOCK:
									SM_Sub_EraseFirstArea(e_ECUID);
									break;
								case ConfigFlash.e_Flash_States.WRITE_FIRST_BLOCK:
									SM_Sub_ProgrammFirstArea(e_ECUID);
									break;
								case ConfigFlash.e_Flash_States.ERASE_BLOCKS:
									SM_Sub_EraseArea23(e_ECUID);
									break;
								case ConfigFlash.e_Flash_States.WRITE_BLOCKS:
									SM_Sub_ProgrammArea23(e_ECUID);
									break;
								case ConfigFlash.e_Flash_States.RESET_ECU:
									SM_Sub_ResetECUs(e_ECUID);
									break;
								default:
									Console.WriteLine("SM_Main() Falsche Value: flashState = {0}", flashState);
									flashState = ConfigFlash.e_Flash_States.ERROR;
									break;
								}
							}
							while (flashState != ConfigFlash.e_Flash_States.DTC_MBLOCK_VERIFY && flashState != ConfigFlash.e_Flash_States.ERROR);
							if (flashState == ConfigFlash.e_Flash_States.ERROR)
							{
								break;
							}
							if (e_ECUID == ConfigData.e_ECUID.A)
							{
								currentFlashECU = baseServiceB;
								currentFlashECU.Diagnose_stop();
							}
							else
							{
								Thread.Sleep(100);
							}
						}
						if (flashState == ConfigFlash.e_Flash_States.DTC_MBLOCK_VERIFY)
						{
							SM_Sub_DTC_MBlock_Verify();
							if (flashState == ConfigFlash.e_Flash_States.FINISHED)
							{
								string text = dtcText_SM_Main;
								if (notChangedECUA)
								{
									text += "ECU A not flashed because software is already installed!\n";
								}
								if (notChangedECUB)
								{
									text += "ECU B not flashed because software is already installed!\n";
								}
								if (this.ev_AddConsoleEvent != null)
								{
									this.ev_AddConsoleEvent(text, Color.Black, "");
								}
								if (this.ev_ProgressStep != null)
								{
									this.ev_ProgressStep(this, new ServiceLayerStringEventArg("Finished"));
								}
								if (this.ev_ProgressClose != null)
								{
									this.ev_ProgressClose(this, new ServiceLayerBoolEventArg(true));
								}
								if (this.ev_Flash_Successful != null)
								{
									this.ev_Flash_Successful(this, new ServiceLayerStringEventArg(text));
								}
								flash_container = null;
							}
						}
						if (flashState == ConfigFlash.e_Flash_States.ERROR)
						{
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Error during flash procedure, process aborted.\r\n" + errorMessage, Color.Black, "");
							}
							if (this.ev_ProgressClose != null)
							{
								this.ev_ProgressClose(this, new ServiceLayerBoolEventArg(false));
							}
							if (this.ev_Flash_Error != null)
							{
								this.ev_Flash_Error(this, new ServiceLayerStringEventArg(errorMessage));
							}
							flash_container = null;
						}
						flashState = ConfigFlash.e_Flash_States.FINISHED;
						if (flash_container != null)
						{
							flash_container = null;
						}
						if (flash_containerA != null)
						{
							flash_containerA = null;
						}
						if (flash_containerB != null)
						{
							flash_containerB = null;
						}
						break;
					}
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent(exitReason, Color.Black, "");
					}
					throw new FlashAbortExeption(string.Format("File is not a valid - for this ECU\r\nERROR: {0}", exitReason));
				}
				return;
			}
			flashState = ConfigFlash.e_Flash_States.ERROR;
			throw new FlashAbortExeption("Flash condition evaluation of both ECUs failed, SW-update process prohibited, engine unserviceable;\r\n Restart Wizard and tray again; Please contact Austro Engine After Sales.");
		}

		private MemoryStream SecurityDecryptFile(string file, string zauberwort)
		{
			CryptedCompression cryptedCompression = new CryptedCompression();
			FileStream fileStream = File.OpenRead(file);
			MemoryStream memoryStream = new MemoryStream();
			memoryStream.SetLength(fileStream.Length);
			fileStream.Read(memoryStream.GetBuffer(), 0, (int)fileStream.Length);
			memoryStream.Flush();
			fileStream.Close();
			MemoryStream result = cryptedCompression.DecryptStream(memoryStream, zauberwort, bufEncrypted);
			memoryStream.Close();
			return result;
		}

		private bool FC_ContainerLoad()
		{
			bool result = false;
			errorMessage = string.Empty;
			CryptedCompression cryptedCompression = new CryptedCompression();
			XmlLogFlashContainer xmlLogFlashContainer = new XmlLogFlashContainer();
			XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
			xmlReaderSettings.DtdProcessing = DtdProcessing.Ignore;
			MemoryStream memoryStream = new MemoryStream();
			MemoryStream memoryStream2 = new MemoryStream();
			MemoryStream memoryStream3 = new MemoryStream();
			string extension = Path.GetExtension(flashContainerPath);
			try
			{
				if (!(extension == ConfigData.WizardEncryptedOutput_FileExtension) && (!(extension == ".xml") || !ConfigFlash.FctClearText))
				{
					throw new FlashAbortExeption("Wrong file-type, should be: " + ConfigData.WizardEncryptedOutput_FileExtension);
				}
				byte[] array = new byte[4];
				uint num = 0u;
				uint num2 = 0u;
				if (!ConfigFlash.FctClearText)
				{
					memoryStream = SecurityDecryptFile(flashContainerPath, ConfigSecurity.Zauberwort);
					if (memoryStream == null)
					{
						throw new FlashAbortExeption("Error when decrypting file (FCT)!");
					}
					if (memoryStream.Position != 0)
					{
						memoryStream.Position = 0L;
					}
					memoryStream.Read(array, 0, 4);
					num = (uint)((array[0] << 24) + (array[1] << 16) + (array[2] << 8) + array[3]);
					memoryStream2.SetLength(memoryStream.Length - 4);
					memoryStream.Position = 4L;
					memoryStream.Read(memoryStream2.GetBuffer(), 0, (int)memoryStream.Length - 4);
					memoryStream2.Flush();
					memoryStream.Close();
					num2 = ChecksumCalc(new List<byte>(memoryStream2.GetBuffer()));
					if (num2 != num)
					{
						throw new FlashAbortExeption("Checksum error when decoding flash container!");
					}
					memoryStream3 = new MemoryStream(bufUnModified, 0, cryptedCompression.GZipDecompress(memoryStream2, bufUnModified), true, true);
					if (memoryStream2 != null)
					{
						memoryStream2.Close();
					}
				}
				else
				{
					FileStream fileStream = File.OpenRead(flashContainerPath);
					memoryStream3 = new MemoryStream();
					memoryStream3.SetLength(fileStream.Length);
					fileStream.Read(memoryStream3.GetBuffer(), 0, (int)fileStream.Length);
					memoryStream3.Flush();
					fileStream.Close();
				}
				ConfigData.e_FileTypes e_FileTypes = xmlLogFlashContainer.ReadFiletype(memoryStream3);
				if (e_FileTypes != ConfigData.e_FileTypes.FLASH_CONTAINER)
				{
					throw new FlashAbortExeption(string.Format("File is not a valid {0} - File\r\nIt's of type: {1}", ConfigData.e_FileTypes.FLASH_CONTAINER, e_FileTypes));
				}
				memoryStream3.Position = 0L;
				xmlReaderSettings.DtdProcessing = DtdProcessing.Parse;
				XmlReader reader = XmlReader.Create(memoryStream3, xmlReaderSettings);
				xmlLogFlashContainer.ReadFlashContainer(reader, ref flash_containerA, ref flash_containerB);
				if (xmlLogFlashContainer.XMLWizardScript != null && xmlLogFlashContainer.XMLWizardScript != string.Empty)
				{
					XMLWizardScript = xmlLogFlashContainer.XMLWizardScript;
					fscriptLayer.ScriptRun(this, new ServiceLayerStringEventArg(XMLWizardScript));
					xmlLogFlashContainer.XMLWizardScript = string.Empty;
					XMLWizardPostScript = xmlLogFlashContainer.XMLWizardPostScript;
				}
				selectedFCTVer = flash_containerA.TestFCData();
				flash_containerB.TestFCData();
				if (flash_containerA != null)
				{
					result = true;
				}
			}
			catch (FlashAbortExeption flashAbortExeption)
			{
				if (memoryStream != null)
				{
					memoryStream.Close();
				}
				if (memoryStream2 != null)
				{
					memoryStream2 = new MemoryStream();
				}
				if (memoryStream3 != null)
				{
					memoryStream3 = new MemoryStream();
				}
				throw new FlashAbortExeption(flashAbortExeption.Message);
			}
			catch (Exception ex)
			{
				if (memoryStream != null)
				{
					memoryStream.Close();
				}
				if (memoryStream2 != null)
				{
					memoryStream2 = new MemoryStream();
				}
				if (memoryStream3 != null)
				{
					memoryStream3 = new MemoryStream();
				}
				throw new FlashAbortExeption("Error when parsing flash container!\n" + ex.Message);
			}
			if (this.ev_ProgressSetup != null)
			{
				this.ev_ProgressSetup(this, new ServiceLayerProgressSetupEventArg("Parsing flash container", flash_containerA));
			}
			return result;
		}

		private List<byte> HexFileReadIn(string filename)
		{
			MemoryStream memoryStream = new MemoryStream();
			FileStream fileStream = File.OpenRead(filename);
			try
			{
				memoryStream = new MemoryStream();
				memoryStream.SetLength(fileStream.Length);
				fileStream.Read(memoryStream.GetBuffer(), 0, (int)fileStream.Length);
				memoryStream.Flush();
				fileStream.Close();
				memoryStream.Position = 0L;
				byte[] array = new byte[memoryStream.Length];
				memoryStream.Read(array, 0, (int)memoryStream.Length);
				if (memoryStream != null)
				{
					memoryStream.Close();
				}
				return new List<byte>(array);
			}
			catch
			{
				if (memoryStream != null)
				{
					memoryStream.Close();
				}
				if (fileStream != null)
				{
					fileStream.Close();
				}
			}
			return new List<byte>();
		}

		private void TimingParameterWrite(ConfigFlash.e_timingParameter e_timing, ConfigData.e_ECUID ecuID)
		{
			List<byte> list = new List<byte>();
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Writing timing parameters: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			list = flashService.TimingParameterAccess(e_timing);
			foreach (byte item in list)
			{
				if (this.ev_AddConsoleEvent != null)
				{
					this.ev_AddConsoleEvent("0x" + string.Format("{0:X2}", item), Color.Black, string.Concat("ECU ", ecuID, ": "));
				}
			}
		}

		private void SM_Sub_FingerprintWrite(ConfigData.e_ECUID ecuID)
		{
			List<byte> list = new List<byte>();
			flashState = ConfigFlash.e_Flash_States.ERROR;
			if (this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", currentFlashECU.EcuId, ": Writing fingerprint")));
			}
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Writing fingerprint: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			ushort num = (ushort)ConfigSecurity.DongleCode(baseServiceA.BaseServSecurityAccessRight());
			list.Add(0);
			list.Add(0);
			list.Add(BaseService.TransformIntToBCD(DateTime.Now.Year % 2000));
			list.Add(BaseService.TransformIntToBCD(DateTime.Now.Month));
			list.Add(BaseService.TransformIntToBCD(DateTime.Now.Day));
			list.Add(174);
			list.Add(174);
			list.Add((byte)((num & 0xFF00) >> 8));
			list.Add((byte)(num & 0xFF));
			flashService.DataWriteByLID(list);
			flashState = ConfigFlash.e_Flash_States.FILTER_BLOCKS_ALREADY_IN_ECU;
		}

		private void FingerPrintRead(ConfigData.e_ECUID ecuID)
		{
			List<byte> list = new List<byte>();
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Reading fingerprint: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			list = flashService.DataReadByLID();
			WriteResponseToConsole(list);
		}

		private EVerifyFlashConditions ECUActiveTest()
		{
			EVerifyFlashConditions eVerifyFlashConditions = EVerifyFlashConditions.eNoActiveECUSite;
			if (ConfigFlash.IgnoreFlashCond || flash_container.Conditions_ignore)
			{
				if (this.ev_AddConsoleEvent != null)
				{
					this.ev_AddConsoleEvent("Flash conditions ignored due to OEM-mode / FCT.", Color.Black, "ECUA and ECUB:");
				}
				eVerifyFlashConditions = EVerifyFlashConditions.eIgnoreFlCond;
			}
			else
			{
				if (baseServiceA.EcuData.EcuSwVersion == "not available")
				{
					baseServiceA.EcuData.EcuSerialNumber = baseServiceB.EcuData.EcuSerialNumber;
					baseServiceA.EcuData.EcuSwVersion = baseServiceB.EcuData.EcuSwVersion;
					baseServiceA.EcuData.EcuSerialNumber = baseServiceB.EcuData.EcuSerialNumber;
					baseServiceA.EcuData.EngineType = baseServiceB.EcuData.EngineType;
					baseServiceA.EcuData.EcuHwVersionReadable = baseServiceB.EcuData.EcuHwVersionReadable;
				}
				else
				{
					eVerifyFlashConditions = EVerifyFlashConditions.eonlyAECUActive;
				}
				if (baseServiceB.EcuData.EcuSwVersion == "not available")
				{
					baseServiceB.EcuData.EcuSerialNumber = baseServiceA.EcuData.EcuSerialNumber;
					baseServiceB.EcuData.EcuSwVersion = baseServiceA.EcuData.EcuSwVersion;
					baseServiceB.EcuData.EcuSerialNumber = baseServiceA.EcuData.EcuSerialNumber;
					baseServiceB.EcuData.EngineType = baseServiceA.EcuData.EngineType;
					baseServiceB.EcuData.EcuHwVersionReadable = baseServiceA.EcuData.EcuHwVersionReadable;
				}
				else
				{
					switch (eVerifyFlashConditions)
					{
					case EVerifyFlashConditions.eonlyAECUActive:
						eVerifyFlashConditions = EVerifyFlashConditions.eBothECUActive;
						break;
					case EVerifyFlashConditions.eNoActiveECUSite:
						eVerifyFlashConditions = EVerifyFlashConditions.eonlyBECUActive;
						break;
					}
				}
			}
			return eVerifyFlashConditions;
		}

		private void TH_FlashRoutineComplete()
		{
			flashIterationCounter = 1;
			currentFlashECU = baseServiceA;
			if (!ECU_VerifyBothConnected())
			{
				return;
			}
			try
			{
				do
				{
					if (bFTCOk)
					{
						Log_Init();
						SM_Main();
						if (ConfigFlash.IgnoreFlashCond && this.ev_flasLayer_FlashCondIgnoreChanged != null)
						{
							this.ev_flasLayer_FlashCondIgnoreChanged(null, new ServiceLayerBoolEventArg(false));
						}
						continue;
					}
					if (ConfigFlash.IgnoreFlashCond && this.ev_flasLayer_FlashCondIgnoreChanged != null)
					{
						this.ev_flasLayer_FlashCondIgnoreChanged(null, new ServiceLayerBoolEventArg(false));
					}
					throw new FlashAbortExeption(errorMessage);
				}
				while (flashState != ConfigFlash.e_Flash_States.ERROR && flashState != ConfigFlash.e_Flash_States.FINISHED);
			}
			catch (Exception ex)
			{
				flashState = ConfigFlash.e_Flash_States.ERROR;
				if (this.ev_Flash_Error != null)
				{
					this.ev_Flash_Error(this, new ServiceLayerStringEventArg(ex.Message));
				}
				errorMessage = ex.Message;
				AbortThread();
			}
			baseServiceA.CommunicationStop();
			baseServiceB.CommunicationStop();
			if (this.ev_SessionLogTriggerSave != null)
			{
				this.ev_SessionLogTriggerSave(this, null);
			}
			Log_Save();
			if (XMLWizardPostScript != null && XMLWizardPostScript != string.Empty && flashState != ConfigFlash.e_Flash_States.ERROR)
			{
				fscriptLayer.ScriptRun(this, new ServiceLayerStringEventArg(XMLWizardPostScript));
				XMLWizardPostScript = string.Empty;
			}
		}

		private void SM_Sub_SkipRedundantAreas(ConfigData.e_ECUID ecuID)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int i = 0;
			bool flag = true;
			new List<byte>(3);
			if (ConfigFlash.FlashVerbose)
			{
				flashState = ConfigFlash.e_Flash_States.ERASE_FIRST_BLOCK;
				return;
			}
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Erasing flash: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			if (flash_container.FlashBlockAreas.Count > 0 && this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Format("ECU {0}: SW version to flash already in ECU, checking CRC to skip valid blocks.", ecuID)));
			}
			while (num < flash_container.FlashBlockAreas.Count)
			{
				FlashBlock flashBlock = flash_container.FlashBlockAreas[num];
				if (num2 > ConfigFlash.RetryAttepts || num2 < 0)
				{
					break;
				}
				try
				{
					if (flashBlock.BlockCheckable)
					{
						if (num == 0)
						{
							for (; i < flashBlock.Flashdatablocks.Count; i++)
							{
								flashService.StartChecksumCalculation(flashBlock.Flashdatablocks[i].ChksumStartAdr, flashBlock.Flashdatablocks[i].ChksumEndAdr, flashBlock.Flashdatablocks[i].CheckSum);
								List<byte> list = flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResChkSum);
								WriteResponseToConsole(list);
							}
							if (flag)
							{
								flashBlock.BlockProgrammable = false;
								flashBlock.BlockEraseable = false;
								if (this.ev_AddConsoleEvent != null)
								{
									this.ev_AddConsoleEvent(string.Format("Flash area {0} already in ECU!", num + 1), Color.Black, string.Format("ECU {0}: ", ConfigData.ECUString[(int)ecuID]));
								}
								if (this.ev_ProgressStep != null)
								{
									this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Format("ECU {0}:  Checking CRC to skip valid blocks. Check flash area {1}", ecuID, num + 1)));
								}
							}
						}
						else if (num == 2 && !flag)
						{
							flashBlock.BlockProgrammable = true;
							flashBlock.BlockEraseable = true;
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Flash area " + (num + 1) + " already in ECU. Rewrite!", Color.Black, string.Format("ECU {0}: ", ConfigData.ECUString[(int)ecuID]));
							}
							if (this.ev_ProgressStep != null)
							{
								this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Format("ECU {0}:  Checking CRC to skip valid blocks. Check flash area {1}", ecuID, num + 1)));
							}
						}
						else
						{
							flashService.StartChecksumCalculation(flashBlock.ChksumStartAdr, flashBlock.ChksumEndAdr, flashBlock.CheckSum);
							Thread.Sleep(5);
							List<byte> list = flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResChkSum);
							WriteResponseToConsole(list);
							flashBlock.BlockProgrammable = false;
							flashBlock.BlockEraseable = false;
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Flash area " + (num + 1) + " already in ECU!", Color.Black, string.Format("ECU {0}: ", ConfigData.ECUString[(int)ecuID]));
							}
							if (this.ev_ProgressStep != null)
							{
								this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Format("ECU {0}:  Checking CRC to skip valid blocks. Check flash area {1}", ecuID, num + 1)));
							}
						}
						num2 = 0;
						num3 = 0;
					}
					num++;
				}
				catch (ECUSendErrorException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unable to send request", Color.Black, "            ");
					}
					num2++;
				}
				catch (ECUResponseTimeoutException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Timeout error", Color.Black, "            ");
					}
					try
					{
						currentFlashECU.Diagnose_stop();
						currentFlashECU.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.Diagnostic));
					}
					catch
					{
					}
					throw new FlashAbortExeption("ECU response timeout!");
				}
				catch (ECUResponseNegativeException ex3)
				{
					ErrorReportNegResponse(Convert.ToByte(ex3.Message));
					if (num3++ > 0)
					{
						num++;
						num3 = 0;
						num2 = 0;
						i++;
						flag = false;
					}
				}
				catch (ECUResponseUnkownException ex4)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unknown response: " + ex4.Message, Color.Black, "            ");
					}
					if (num3++ > 1)
					{
						num++;
						num3 = 0;
						num2 = 0;
						i++;
						flag = false;
						flashState = ConfigFlash.e_Flash_States.ERROR;
					}
				}
				catch (ECUDisconnectedExeption)
				{
					flashState = ConfigFlash.e_Flash_States.ERROR;
					throw new FlashAbortExeption("ECU is disconnected");
				}
			}
			if (num == 3 && flashState != ConfigFlash.e_Flash_States.ERROR)
			{
				flashState = ConfigFlash.e_Flash_States.ERASE_FIRST_BLOCK;
			}
		}

		private void SM_Sub_ProgrammFirstArea(ConfigData.e_ECUID ecuID)
		{
			int num = 0;
			uint num2 = 0u;
			uint num3 = 0u;
			flashState = ConfigFlash.e_Flash_States.ERROR;
			if (this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Starting programming Bootblock [PA]")));
			}
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Programming Area: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			FlashBlock flashBlock = flash_container.FlashBlockAreas[0];
			if (flashBlock.BlockProgrammable)
			{
				WriteResponseToConsole(flashService.TimingParameterAccess(ConfigFlash.e_timingParameter.writeFlash));
			}
			else
			{
				num = 1;
				flashState = ConfigFlash.e_Flash_States.ERASE_BLOCKS;
			}
			while (num < 1)
			{
				int num4 = 0;
				int num5 = 0;
				if (num3 > ConfigFlash.RetryAttepts || num3 < 0)
				{
					throw new FlashAbortExeption(string.Format("ECU {0}: Max. number of retries exceeded flashing area {1}.", ConfigData.ECUString[(int)ecuID], flashBlock.Id.ToString()));
				}
				if (flashBlock.BlockProgrammable)
				{
					num2++;
					if (flashBlock.Flashdatablocks.Count > 0 && this.ev_ProgressStep != null)
					{
						this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Programming block ID ", flashBlock.Flashdatablocks[0].Id, ", datablock ", flashBlock.Flashdatablocks[0].Number)));
					}
					while (num4 < flashBlock.Flashdatablocks.Count)
					{
						try
						{
							FlashBlockData flashBlockData = flashBlock.Flashdatablocks[num4];
							if (num5 > ConfigFlash.RetryAttepts || num5 < 0)
							{
								throw new FlashAbortExeption(string.Concat("ECU ", ecuID, ": Max. number of retries exceeded writing block ", flashBlockData.Id.ToString(), "."));
							}
							if (num5 > 0)
							{
								num = 1;
								flashState = ConfigFlash.e_Flash_States.ERASE_FIRST_BLOCK;
								num5--;
								break;
							}
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Programming block ID " + flashBlockData.Id + ", datablock " + flashBlockData.Number, Color.Black, string.Concat("ECU ", ecuID, ": "));
							}
							flashService.RequestDownload(flashBlockData.WriteStartAdr, flashBlockData.Length);
							Thread.Sleep(10);
							TransferDataBlock(flashBlockData.WriteStartAdr, flashBlockData.Buffer, (int)flashBlockData.Length, ecuID);
							Thread.Sleep(5);
							flashService.TransferExit();
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("TransferExit()", Color.Black, string.Concat("ECU ", ecuID, ": "));
							}
							num4++;
							num5 = 0;
							if (num4 < flashBlock.Flashdatablocks.Count && this.ev_ProgressStep != null)
							{
								this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Programming block ID ", flashBlockData.Id, ", datablock ", flashBlockData.Number)));
							}
						}
						catch (ECUSendErrorException)
						{
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Unable to send request", Color.Black, "            ");
							}
							num5++;
						}
						catch (ECUResponseTimeoutException)
						{
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Timeout error", Color.Black, "            ");
							}
							try
							{
								currentFlashECU.Diagnose_stop();
								currentFlashECU.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.Diagnostic));
							}
							catch
							{
							}
							throw new FlashAbortExeption("ECU response timeout!");
						}
						catch (ECUResponseNegativeException ex3)
						{
							ErrorReportNegResponse(Convert.ToByte(ex3.Message));
							num5++;
						}
						catch (ECUResponseUnkownException ex4)
						{
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Unknown Response: " + ex4.Message, Color.Black, "            ");
							}
							num5++;
						}
						catch (ECUDisconnectedExeption)
						{
							throw new FlashAbortExeption("ECU is disconnected");
						}
					}
				}
				if (num3 > ConfigFlash.RetryAttepts)
				{
					throw new FlashAbortExeption(string.Concat("ECU ", ecuID, ": Max. number of retries exceeded writing Area ", flashBlock.Id.ToString(), "."));
				}
				if (num != 0)
				{
					continue;
				}
				try
				{
					if (!flashBlock.BlockCheckable)
					{
						num3 = 0u;
						num++;
						continue;
					}
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Verifying complete block ID " + flashBlock.Id, Color.Black, string.Concat("ECU ", ecuID, ": "));
					}
					Thread.Sleep(5);
					flashService.StartChecksumCalculation(flashBlock.ChksumStartAdr, flashBlock.ChksumEndAdr, flashBlock.CheckSum);
					WriteResponseToConsole(flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResChkSum));
					num3 = 0u;
					flashService.ECUResetFlash();
					Thread.Sleep(2500);
					SM_Sub_FingerprintWrite(ecuID);
					num++;
				}
				catch (ECUSendErrorException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unable to send request", Color.Black, "            ");
					}
					num3++;
				}
				catch (ECUResponseTimeoutException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Timeout error", Color.Black, "            ");
					}
					try
					{
						currentFlashECU.Diagnose_stop();
						currentFlashECU.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.Diagnostic));
					}
					catch
					{
					}
					throw new FlashAbortExeption("ECU response timeout!");
				}
				catch (ECUResponseNegativeException ex7)
				{
					ErrorReportNegResponse(Convert.ToByte(ex7.Message));
					num3++;
					continue;
				}
				catch (ECUResponseUnkownException ex8)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unknown response: " + ex8.Message, Color.Black, "            ");
					}
					num3++;
				}
				catch (ECUDisconnectedExeption)
				{
					throw new FlashAbortExeption("ECU is disconnected");
				}
				flashState = ConfigFlash.e_Flash_States.ERASE_BLOCKS;
			}
		}

		private void SM_Sub_ProgrammArea23(ConfigData.e_ECUID ecuID)
		{
			int num = 0;
			int num2 = 1;
			int connectAttempts = ConfigData.ConnectAttempts;
			int num3 = ConfigData.ConnectAttempts;
			if (this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Starting programming")));
			}
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Programming Area: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			WriteResponseToConsole(flashService.TimingParameterAccess(ConfigFlash.e_timingParameter.writeFlash));
			while (num2 < flash_container.FlashBlockAreas.Count)
			{
				FlashBlock flashBlock = flash_container.FlashBlockAreas[num2];
				num = 0;
				if (connectAttempts > ConfigFlash.RetryAttepts)
				{
					throw new FlashAbortExeption(string.Concat("ECU ", ecuID, ": Max. number of retries exceeded when area ", flashBlock.Id.ToString(), "."));
				}
				if (flashBlock.BlockProgrammable)
				{
					if (this.ev_ProgressStep != null)
					{
						this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Programming block ID ", flashBlock.Flashdatablocks[0].Id, ", datablock ", flashBlock.Flashdatablocks[num].Number)));
					}
					while (num < flashBlock.Flashdatablocks.Count)
					{
						try
						{
							FlashBlockData flashBlockData = flashBlock.Flashdatablocks[num];
							if (num3 > ConfigFlash.RetryAttepts)
							{
								throw new FlashAbortExeption(string.Concat("ECU ", ecuID, ": Max. number of retries exceeded writing block ", flashBlockData.Id.ToString(), "."));
							}
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Programming block ID " + flashBlockData.Id + ", datablock " + flashBlockData.Number, Color.Black, string.Concat("ECU ", ecuID, ": "));
							}
							if (this.ev_ProgressStep != null)
							{
								this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Programming block ID ", flashBlockData.Id, ", datablock ", flashBlockData.Number)));
							}
							flashService.RequestDownload(flashBlockData.WriteStartAdr, flashBlockData.Length);
							Thread.Sleep(4);
							TransferDataBlock(flashBlockData.WriteStartAdr, flashBlockData.Buffer, (int)flashBlockData.Length, ecuID);
							Thread.Sleep(5);
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("TransferExit()", Color.Black, string.Concat("ECU ", ecuID, ": "));
							}
							flashService.TransferExit();
							num++;
							num3 = 0;
						}
						catch (ECUSendErrorException)
						{
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Unable to send request", Color.Black, "            ");
							}
							num3++;
						}
						catch (ECUResponseTimeoutException)
						{
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Timeout error", Color.Black, "            ");
							}
							try
							{
								currentFlashECU.Diagnose_stop();
								currentFlashECU.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.Diagnostic));
							}
							catch
							{
							}
							throw new FlashAbortExeption("ECU response timeout!");
						}
						catch (ECUResponseNegativeException ex3)
						{
							ErrorReportNegResponse(Convert.ToByte(ex3.Message));
							num3++;
						}
						catch (ECUResponseUnkownException ex4)
						{
							if (this.ev_AddConsoleEvent != null)
							{
								this.ev_AddConsoleEvent("Unknown response: " + ex4.Message, Color.Black, "            ");
							}
							num3++;
						}
						catch (ECUDisconnectedExeption)
						{
							throw new FlashAbortExeption("ECU is disconnected");
						}
					}
					num2++;
				}
				else
				{
					num2++;
					connectAttempts = ConfigData.ConnectAttempts;
				}
			}
			if (connectAttempts < 0)
			{
				flashState = ConfigFlash.e_Flash_States.ERROR;
			}
			connectAttempts--;
			if (flashState != ConfigFlash.e_Flash_States.ERROR)
			{
				flashState = ConfigFlash.e_Flash_States.RESET_ECU;
			}
		}

		private void SM_Sub_DTC_MBlock_Verify()
		{
			int num = 0;
			bool flag = true;
			if (this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg("ECU A+B: Verifying block memory failure"));
			}
			Thread.Sleep(1000);
			this.ev_DTC_Clear(this, new EventArgs());
			processActive[0] = true;
			while (processActive[0])
			{
				Application.DoEvents();
				Thread.Sleep(20);
				num += 20;
				if (num >= 10000 || processError[0])
				{
					processError[0] = false;
					processActive[0] = false;
					throw new FlashAbortExeption("DTC: memory block failure could not be evaluated");
				}
			}
			num = 0;
			Thread.Sleep(300);
			this.ev_DTC_Read(this, new EventArgs());
			while (processActive[1])
			{
				Application.DoEvents();
				Thread.Sleep(20);
				num += 20;
				if (num >= 10000 || processError[1])
				{
					processError[1] = false;
					processActive[1] = false;
					throw new FlashAbortExeption("DTC: memory block failure could not be evaluated");
				}
			}
			Console.WriteLine("Count of baseServiceA.EcuData.DTCArray = {0}; Count of baseServiceB.EcuData.DTCArray = {1}", baseServiceA.EcuData.DTCArray.Length, baseServiceB.EcuData.DTCArray.Length);
			DTC[] dTCArray = baseServiceA.EcuData.DTCArray;
			foreach (DTC dTC in dTCArray)
			{
				if (dTC.id == 9060)
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				DTC[] dTCArray2 = baseServiceB.EcuData.DTCArray;
				foreach (DTC dTC2 in dTCArray2)
				{
					if (dTC2.id == 9060)
					{
						flag = false;
						break;
					}
				}
			}
			if (flag)
			{
				flashState = ConfigFlash.e_Flash_States.FINISHED;
				return;
			}
			flashState = ConfigFlash.e_Flash_States.ERROR;
			errorMessage = "Block memory fault appeared!";
			string text = "Error during flash process, aborted!\r\nBlock memory fault appeared. Please repeat flash process.";
			MessageBox.Show(text, ConfigData.WizardSwName);
		}

		private string SM_Sub_FCM_Check(ushort iterationCount)
		{
			if (this.ev_AddConsoleEvent != null)
			{
				this.ev_AddConsoleEvent("Looking for active DTCs, auto-saving engine log", Color.Black, "       ");
			}
			string empty = string.Empty;
			string text = ConfigFlash.EngineLog_AutoBackup_Filename + "_" + DateTime.UtcNow.ToString("yyyyMMdd_HHmmss") + ConfigData.WizardEncryptedOutput_FileExtension;
			int num = 0;
			if (iterationCount != 1)
			{
				return empty;
			}
			if (this.ev_EngLog_Save != null)
			{
				this.ev_EngLog_Save(this, new ServiceLayerStringEventArg(text));
			}
			if (this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg("Saving engine log"));
			}
			Thread.Sleep(20);
			processActive[2] = true;
			processError[2] = false;
			num = 0;
			while (processActive[2])
			{
				Application.DoEvents();
				Thread.Sleep(20);
				if (num++ >= 3000 || processError[2])
				{
					processActive[2] = false;
					processError[2] = false;
					throw new FlashAbortExeption("Engine - log could not be saved! Operation timed out!");
				}
			}
			Console.WriteLine("SM_Sub_FCM_Check; counter = {0};", num);
			empty = ((baseServiceA.EcuData.DTCArray.Length != 0 || baseServiceB.EcuData.DTCArray.Length != 0) ? ("The following number of DTCs were detected in the ECUs:\r\n\r\nECU A: " + baseServiceA.EcuData.DTCArray.Length + "\r\nECU B: " + baseServiceB.EcuData.DTCArray.Length + "\r\n\r\nAn engine log has automatically been saved with the filename: " + text + "\r\n\n") : ("No DTCs were detected in the ECU, an engine log has been stored with the filename: " + text + "\r\n\n"));
			if (this.ev_AddConsoleEvent != null)
			{
				this.ev_AddConsoleEvent(empty, Color.Black, "");
			}
			processActive[0] = true;
			processError[0] = false;
			if (this.ev_DTC_Clear != null)
			{
				this.ev_DTC_Clear(this, null);
			}
			num = 0;
			while (processActive[0])
			{
				Application.DoEvents();
				Thread.Sleep(20);
				num++;
				if (num >= 400 || processError[0])
				{
					processActive[0] = false;
					processError[0] = false;
					throw new FlashAbortExeption("FCM could not be cleared!");
				}
			}
			return empty;
		}

		private void SM_Sub_ResetECUs(ConfigData.e_ECUID ecuID)
		{
			if (ecuID == ConfigData.e_ECUID.A)
			{
				if (this.ev_ProgressStep != null)
				{
					this.ev_ProgressStep(this, new ServiceLayerStringEventArg("ECU A: Reset"));
				}
				baseServiceA.ECU_Reset();
			}
			else
			{
				if (this.ev_ProgressStep != null)
				{
					this.ev_ProgressStep(this, new ServiceLayerStringEventArg("ECU B: Reset"));
				}
				baseServiceB.ECU_Reset();
			}
			flashState = ConfigFlash.e_Flash_States.DTC_MBLOCK_VERIFY;
		}

		private void SM_Sub_EraseFirstArea(ConfigData.e_ECUID ecuID)
		{
			int num = 0;
			int num2 = 0;
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Erasing flash: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			FlashBlock flashBlock = flash_container.FlashBlockAreas[0];
			while (num < 1)
			{
				try
				{
					uint num3 = 0u;
					uint num4 = 0u;
					List<byte> list = new List<byte>();
					if (num2 > ConfigFlash.RetryAttepts || num2 < 0)
					{
						throw new FlashAbortExeption(string.Concat("ECU ", ecuID, ": Max. number of retries exceeded when erasing block ", flashBlock.Id.ToString(), "."));
					}
					if (!flashBlock.BlockEraseable)
					{
						num++;
						num2 = 0;
						continue;
					}
					if (this.ev_ProgressStep != null)
					{
						this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Erasing flash block ", flashBlock.Id.ToString())));
					}
					if (num == 0)
					{
						WriteResponseToConsole(flashService.TimingParameterAccess(ConfigFlash.e_timingParameter.eraseFlash));
					}
					WriteResponseToConsole(flashService.StartFlashErase(flashBlock.EraseStartAdr, flashBlock.EraseEndAdr));
					Thread.Sleep(5);
					WriteResponseToConsole(flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResErase));
					num3 = flashBlock.EraseEndAdr - flashBlock.EraseStartAdr + 1;
					for (int i = 0; i < num3; i++)
					{
						list.Add(byte.MaxValue);
					}
					num4 = ChecksumCalc(list);
					Thread.Sleep(5);
					flashService.StartChecksumCalculation(flashBlock.EraseStartAdr, flashBlock.EraseEndAdr, num4);
					WriteResponseToConsole(flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResChkSum));
					num2 = 0;
					num++;
				}
				catch (ECUSendErrorException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unable to send request", Color.Black, "            ");
					}
					num2++;
				}
				catch (ECUResponseTimeoutException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Timeout error", Color.Black, "            ");
					}
					try
					{
						currentFlashECU.Diagnose_stop();
						currentFlashECU.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.Diagnostic));
					}
					catch
					{
					}
					throw new FlashAbortExeption("Timeout error");
				}
				catch (ECUResponseNegativeException ex3)
				{
					ErrorReportNegResponse(Convert.ToByte(ex3.Message));
					num2++;
				}
				catch (ECUResponseUnkownException ex4)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unknown response: " + ex4.Message, Color.Black, "            ");
					}
					num2++;
				}
				catch (ECUDisconnectedExeption)
				{
					throw new FlashAbortExeption("ECU is disconnected");
				}
			}
			if (flashState != ConfigFlash.e_Flash_States.ERROR)
			{
				flashState = ConfigFlash.e_Flash_States.WRITE_FIRST_BLOCK;
			}
		}

		private void SM_Sub_EraseArea23(ConfigData.e_ECUID ecuID)
		{
			int num = 1;
			int num2 = 0;
			if (this.ev_ProgressStep != null)
			{
				this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", currentFlashECU.EcuId, ": Erasing")));
			}
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Erasing flash: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			uint num3 = 0u;
			while (num < flash_container.FlashBlockAreas.Count)
			{
				try
				{
					num3 = 0u;
					FlashBlock flashBlock = flash_container.FlashBlockAreas[num];
					List<byte> list = new List<byte>();
					if (this.ev_ProgressStep != null)
					{
						this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Erasing flash block ", flashBlock.Id.ToString())));
					}
					if (num2 > ConfigFlash.RetryAttepts || num2 < 0)
					{
						flashState = ConfigFlash.e_Flash_States.ERROR;
						throw new FlashAbortExeption(string.Concat("ECU ", ecuID, ": Max. number of retries exceeded when erasing block ", flashBlock.Id.ToString(), "."));
					}
					if (!flashBlock.BlockEraseable)
					{
						num++;
						num2 = 0;
						continue;
					}
					if (num == 0)
					{
						WriteResponseToConsole(flashService.TimingParameterAccess(ConfigFlash.e_timingParameter.eraseFlash));
					}
					WriteResponseToConsole(flashService.StartFlashErase(flashBlock.EraseStartAdr, flashBlock.EraseEndAdr));
					Thread.Sleep(3);
					WriteResponseToConsole(flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResErase));
					num3 = flashBlock.EraseEndAdr - flashBlock.EraseStartAdr + 1;
					for (int i = 0; i < num3; i++)
					{
						list.Add(byte.MaxValue);
					}
					uint i_checkSum = ChecksumCalc(list);
					Thread.Sleep(10);
					flashService.StartChecksumCalculation(flashBlock.EraseStartAdr, flashBlock.EraseEndAdr, i_checkSum);
					Thread.Sleep(3);
					WriteResponseToConsole(flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResChkSum));
					num2 = 0;
					num++;
					if (num < flash_container.FlashBlockAreas.Count && this.ev_ProgressStep != null)
					{
						this.ev_ProgressStep(this, new ServiceLayerStringEventArg(string.Concat("ECU ", ecuID, ": Erasing flash block ", flash_container.FlashBlockAreas[num].Id.ToString())));
					}
				}
				catch (ECUSendErrorException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unable to send request", Color.Black, "            ");
					}
					num2++;
				}
				catch (ECUResponseTimeoutException)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Timeout error", Color.Black, "            ");
					}
					try
					{
						currentFlashECU.Diagnose_stop();
						currentFlashECU.Diagnose_start(ConfigKWP.DiagMode_Get(ConfigKWP.e_DiagModes.Diagnostic));
					}
					catch
					{
					}
					throw new FlashAbortExeption("Timeout error");
				}
				catch (ECUResponseNegativeException ex3)
				{
					ErrorReportNegResponse(Convert.ToByte(ex3.Message));
					num2++;
					Thread.Sleep(230);
				}
				catch (ECUResponseUnkownException ex4)
				{
					if (this.ev_AddConsoleEvent != null)
					{
						this.ev_AddConsoleEvent("Unknown response: " + ex4.Message, Color.Black, "            ");
					}
					num2++;
					Thread.Sleep(30);
				}
				catch (ECUDisconnectedExeption)
				{
					throw new FlashAbortExeption("ECU is disconnected");
				}
			}
			if (flashState != ConfigFlash.e_Flash_States.ERROR)
			{
				flashState = ConfigFlash.e_Flash_States.WRITE_BLOCKS;
			}
		}

		private void SM_Sub_EraseSingleArea(ConfigData.e_ECUID ecuID, uint startAdr, uint endAdr, bool eraseable)
		{
			uint num = 0u;
			uint num2 = 0u;
			List<byte> list = new List<byte>();
			if (!eraseable)
			{
				return;
			}
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Erasing flash: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			WriteResponseToConsole(flashService.StartFlashErase(startAdr, endAdr));
			WriteResponseToConsole(flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResErase));
			num = endAdr - startAdr + 1;
			for (int i = 0; i < num; i++)
			{
				list.Add(byte.MaxValue);
			}
			num2 = ChecksumCalc(list);
			flashService.StartChecksumCalculation(startAdr, endAdr, num2);
			WriteResponseToConsole(flashService.RequestResult(ConfigKWP.e_kwpServices.Flash_RequestResChkSum));
		}

		private void TransferDataBlock(uint i_startAdr, List<byte> buf, int length, ConfigData.e_ECUID ecuID)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			List<byte> list = new List<byte>(buf);
			IFlashService flashService;
			if (ecuID == baseServiceA.EcuId)
			{
				flashService = flashServiceA;
			}
			else
			{
				if (ecuID != baseServiceB.EcuId)
				{
					throw new FlashAbortExeption("Transfering block data: No valid ECU specified");
				}
				flashService = flashServiceB;
			}
			if (length > buf.Count)
			{
				throw new Exception("FlashLayer.ThreadTransferBlock: length of datablock doesn't match available nr of bytes in buffer!");
			}
			num4 = length / 252;
			if (length % 252 != 0)
			{
				num4++;
			}
			int num5 = 0;
			if (this.ev_ProgressDetailSetup != null)
			{
				this.ev_ProgressDetailSetup(this, new ServiceLayerIntEventArg(num4));
			}
			while (num < length)
			{
				num2 += 251;
				if (num2 >= length)
				{
					num2 = length - 1;
				}
				num3 = num2 - num + 1;
				if (this.ev_AddConsoleEvent != null)
				{
					this.ev_AddConsoleEvent(string.Format("Transferring datablock {0} of {1} (0x{2:X6})", num / 252, num4, i_startAdr + num), Color.Black, string.Format("ECU {0}: ", ConfigData.ECUString[(int)ecuID]));
				}
				flashService.TransferData((byte)num3, new List<byte>(list.GetRange(num, num3)));
				num5++;
				if (this.ev_ProgressDetailStep != null)
				{
					this.ev_ProgressDetailStep(this, new ServiceLayerStringEventArg(string.Format("Transferring datablock {0} of {1}", num / 252, num4 - 1)));
				}
				num = num2 + 1;
			}
			if (this.ev_ProgressDetailClose != null)
			{
				this.ev_ProgressDetailClose(this, new ServiceLayerBoolEventArg(true));
			}
		}

		private uint ChecksumCalc(List<byte> bufAll)
		{
			Crc32 crc = new Crc32();
			crc.Initialize();
			crc.ComputeHash(bufAll.ToArray());
			return crc.CrcValue;
		}

		private uint ChecksumCalc(ref byte[] bufAll)
		{
			Crc32 crc = new Crc32();
			crc.Initialize();
			crc.ComputeHash(bufAll);
			return crc.CrcValue;
		}

		public void WriteResponseToConsole(List<byte> list)
		{
			if (this.ev_AddConsoleEvent == null)
			{
				return;
			}
			foreach (byte item in list)
			{
				this.ev_AddConsoleEvent(string.Format("0x{0:X2}", item), Color.Black, "            ");
			}
		}

		private bool ECU_VerifyBothConnected()
		{
			if (!baseServiceA.ECUisOnline() && !baseServiceB.ECUisOnline())
			{
				MessageBox.Show(ConfigData.WizardSwName + " is not connected!", ConfigData.WizardSwName);
				return false;
			}
			if (!baseServiceA.ECUisOnline())
			{
				MessageBox.Show("ECU A is not connected!\r\nPlease re-establish connection!", ConfigData.WizardSwName);
				return false;
			}
			if (!baseServiceB.ECUisOnline())
			{
				MessageBox.Show("ECU B is not connected!\r\nPlease re-establish connection!", ConfigData.WizardSwName);
				return false;
			}
			return true;
		}

		public void h_ProcessFinished(object sender, ServiceLayerProcessTypeEventArg e)
		{
			processActive[(int)e.ProcessType] = false;
		}

		public void h_ProcessError(object sender, ServiceLayerProcessTypeEventArg e)
		{
			processError[(int)e.ProcessType] = true;
		}
	}
}
